package net.xt.testthread;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class CompletableFutureMallDemo {

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    static class NetMall {

        private String netMallName;

        // 模拟计算价格
        public double calcPrice(String productName) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return ThreadLocalRandom.current().nextDouble() * 100;
        }
    }

    // 初始化数据
    static List<NetMall> list = Arrays.asList(
            new NetMall("jd"),
            new NetMall("taobao"),
            new NetMall("dangdang"));

    /**
     * 方法一：step by step
     */
    public static List<String> getPriceStepByStep(List<NetMall> list, String productName) {
        System.out.println("正在计算…………");

        return list.stream().map(netMall ->
                        String.format("《" + productName + "》" + "in %s price is %.2f",
                                netMall.getNetMallName(),
                                netMall.calcPrice(productName)))
                .collect(Collectors.toList());
    }

    /**
     * 方法二：all in：把list里面的内容映射给CompletableFuture
     */
    public static List<String> getPriceByCompletableFuture(List<NetMall> list, String productName) {
        System.out.println("正在计算…………");

        return list.stream()
                .map(netMall ->
                        // 每个元素开启一个线程CompletableFuture
                        CompletableFuture.supplyAsync(() ->
                                String.format("《" + productName + "》" + "in %s price is %.2f",
                                        netMall.getNetMallName(),
                                        netMall.calcPrice(productName)))) //Stream<CompletableFuture<String>>
                .collect(Collectors.toList()) // List<CompletableFuture<String>>
                .stream()   // Stream<CompletableFuture<String>>
                .map(s -> s.join()) // 启动线程，并发执行
                .collect(Collectors.toList());  //List<String>
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        long StartTime = System.currentTimeMillis();
        List<String> list1 = getPriceStepByStep(list, "mysql");
        for (String element : list1) {
            System.out.println(element);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("------costTime: " + (endTime - StartTime) + " 毫秒");

        System.out.println("分割线=========================");

        long StartTime2 = System.currentTimeMillis();
        List<String> list2 = getPriceByCompletableFuture(list, "mysql");
        for (String element : list2) {
            System.out.println(element);
        }
        long endTime2 = System.currentTimeMillis();
        System.out.println("------costTime：" + (endTime2 - StartTime2) + " 毫秒");

    }

}
